package com.yunc.base.aspect;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.yunc.base.entity.DataScopeEntity;
import com.yunc.base.security.UserEntity;
import com.yunc.base.utils.SecurityUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.List;

/**
 * 数据过滤处理
 */
@Aspect
@Component
public class DataScopeAspect {

    /**
     * 配置织入点
     */
    @Pointcut("@annotation(com.yunc.base.aspect.DataScope)")
    public void dataScopePointCut() {
    }

    @Before("dataScopePointCut()")
    public void doBefore(JoinPoint point) {
        handleDataScope(point);
    }

    protected void handleDataScope(final JoinPoint joinPoint) {
        // 获得注解
        DataScope controllerDataScope = getAnnotationLog(joinPoint);
        if (controllerDataScope == null) {
            return;
        }
        UserEntity user = SecurityUtils.getUser();
        // 用户拥有所有权限
        if (user.getDataScope() <= 0) {
            // 本人所属部门
            dataScopeFilterCustom(joinPoint, user, controllerDataScope.userAlias());
            // 指定部门
            dataScopeFilterDept(joinPoint, user, controllerDataScope.userAlias(), controllerDataScope.deptAlias());
            // 个人
            dataScopeFilterSelf(joinPoint, user, controllerDataScope.userAlias());
        }
    }

    /**
     * 数据范围过滤
     *
     * @param userAlias 用户别名
     * @return 标准连接条件对象
     */
    public static void dataScopeFilterCustom(JoinPoint joinPoint, UserEntity user, String userAlias) {
        StringBuilder sqlString = new StringBuilder();
        List<String> deptIds = user.getDeptIds();
        if (CollUtil.isNotEmpty(deptIds)) {
            // 将deptIds转为string的逗号区分
            sqlString.append(" AND (");
            int count = 0;
            for (String deptId : deptIds) {
                sqlString.append(StrUtil.format(" ( {} IN ( select DISTINCT d.dept_id from sys_user_dept d where {} = d.user_id ) ", deptId, userAlias))
                        .append(" )");
                count++;
                if (count != deptIds.size()) {
                    sqlString.append(" OR");
                }
            }
            sqlString.append(" )");
        } else {
            sqlString.append(StrUtil.format(" OR {}.id = {} ", userAlias, user.getUserId()));
        }
        if (StringUtils.isNotBlank(sqlString.toString())) {
            DataScopeEntity dataScopeEntity = (DataScopeEntity) joinPoint.getArgs()[1];
            dataScopeEntity.setDataScopeParamsCustom(" AND (" + sqlString.substring(4) + ")");
        }
    }

    public static void dataScopeFilterDept(JoinPoint joinPoint, UserEntity user, String userAlias, String deptAlias) {
        StringBuilder sqlString = new StringBuilder();
        List<String> deptIds = user.getDeptIds();
        if (CollUtil.isNotEmpty(deptIds)) {
            // 将deptIds转为string的逗号区分
            sqlString.append(" AND (");
            int count = 0;
            for (String deptId : deptIds) {
                sqlString.append(StrUtil.format(" FIND_IN_SET({}, {}) ", deptId, deptAlias));
                count++;
                if (count != deptIds.size()) {
                    sqlString.append(" OR");
                }
            }
            sqlString.append(" )");
        } else {
            sqlString.append(StrUtil.format(" OR {}.id = {} ", userAlias, user.getUserId()));
        }
        if (StringUtils.isNotBlank(sqlString.toString())) {
            DataScopeEntity dataScopeEntity = (DataScopeEntity) joinPoint.getArgs()[1];
            dataScopeEntity.setDataScopeParamsDept(" AND (" + sqlString.substring(4) + ")");
        }
    }

    public static void dataScopeFilterSelf(JoinPoint joinPoint, UserEntity user, String userAlias) {
        StringBuilder sqlString = new StringBuilder();
        sqlString.append(StrUtil.format(" OR {} = {} ", userAlias, user.getUserId()));
        if (StringUtils.isNotBlank(sqlString.toString())) {
            DataScopeEntity dataScopeEntity = (DataScopeEntity) joinPoint.getArgs()[1];
            dataScopeEntity.setDataScopeParamsSelf(" AND (" + sqlString.substring(4) + ")");
        }
    }

    /**
     * 是否存在注解，如果存在就获取
     */
    private DataScope getAnnotationLog(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if (method != null) {
            return method.getAnnotation(DataScope.class);
        }
        return null;
    }
}
